#include"HashTable.h"

template<class T, class Hash = my_hash<T>>
class unordered_set
{
    typedef T K;
    struct set_K_of_T
    {
        const K& operator() (const T& x) const
        {
            return x;
        }
    };
    HashTable<K, T, set_K_of_T, Hash> _ht;
public:
    typedef typename HashTable<K, T, set_K_of_T, Hash>::iterator iterator;

    pair<iterator, bool> insert(const T& x) 
    { 
        size_t old_size = _ht.size();
        auto p = _ht.insert(x);
        if(_ht.size() == old_size)
            return {p, false};
        else    
            return {p, true};
    }
    iterator begin() { return _ht.begin(); }
    iterator end() { return _ht.end(); }
    iterator find(const K& key) { return _ht.find(key); }
    bool erase(const K& key) { return _ht.erase(key); }
    bool empty() { return _ht.empty(); }
    size_t size() { return _ht.size(); }
};

template<class K, class V, class Hash = my_hash<K>>
class unordered_map
{
    typedef pair<K, V> T;
    struct map_K_of_T
    {
        const K& operator() (const T& x) const
        {
            return x.first;
        }
    };
    HashTable<K, T, map_K_of_T, Hash> _ht;
public:
    typedef typename HashTable<K, T, map_K_of_T, Hash>::iterator iterator;

    pair<iterator, bool> insert(const T& x) 
    { 
        size_t old_size = _ht.size();
        auto p = _ht.insert(x);
        if(_ht.size() == old_size)
            return {p, false};
        else    
            return {p, true};
    }
    iterator begin() { return _ht.begin(); }
    iterator end() { return _ht.end(); }
    iterator find(const K& key) { return _ht.find(key); }
    V& operator[](const K& key)
    {
        return _ht.insert({key, V()})->second;
    }
    bool erase(const K& key) { return _ht.erase(key); }
    bool empty() { return _ht.empty(); }
    size_t size() { return _ht.size(); }
};